package luke.audio.processing;

import luke.audio.analyzer.SpectrumAnalyzer;
import luke.audio.analyzer.UniversalAudioDecoder.AudioData;

/**
 * 音频声道处理器
 * 专门处理音频的声道分离、下采样和频谱分析等操作
 */
public class AudioChannelProcessor {
    
    /**
     * 分离音频数据的指定声道
     * 
     * @param audioData 多声道音频数据
     * @param channel 声道索引（0为左声道，1为右声道）
     * @return 指定声道的音频数据
     */
    public static float[] extractChannel(float[] audioData, int channels, int channel) {
        if (audioData == null || audioData.length == 0 || channels <= 0 || channel < 0 || channel >= channels) {
            throw new IllegalArgumentException("无效的音频数据或声道参数");
        }
        
        int singleChannelLength = audioData.length / channels;
        float[] channelData = new float[singleChannelLength];

        for (int i = 0; i < singleChannelLength; i++) {
            channelData[i] = audioData[i * channels + channel];
        }

        return channelData;
    }
    
    /**
     * 对音频数据进行下采样
     * 
     * @param audioData 原始音频数据
     * @param originalRate 原始采样率
     * @param targetRate 目标采样率
     * @return 下采样后的音频数据
     */
    public static float[] downsample(float[] audioData, int originalRate, int targetRate) {
        if (audioData == null || audioData.length == 0 || originalRate <= 0 || targetRate <= 0) {
            return audioData;
        }
        
        if (originalRate <= targetRate) {
            return audioData;
        }

        // 使用线性插值进行更精确的重采样
        double ratio = (double) originalRate / targetRate;
        int newLength = (int) (audioData.length / ratio);
        float[] downsampled = new float[newLength];

        for (int i = 0; i < newLength; i++) {
            double originalIndex = i * ratio;
            int index1 = (int) Math.floor(originalIndex);
            int index2 = Math.min(index1 + 1, audioData.length - 1);
            double fraction = originalIndex - index1;

            // 线性插值
            if (index1 < audioData.length) {
                downsampled[i] = (float) (audioData[index1] * (1 - fraction) + 
                                         audioData[index2] * fraction);
            }
        }

        return downsampled;
    }
    
    /**
     * 处理双声道音频数据，分离左右声道并计算各自的频谱图
     * 
     * @param audioData 双声道音频数据
     * @param targetRate 目标采样率
     * @param fftSize FFT窗口大小
     * @param hopSize Hop大小
     * @return 包含左右声道频谱图的ChannelSpectrogram对象
     */
    public static ChannelSpectrogram processStereoChannels(AudioData audioData, int targetRate, int fftSize, int hopSize) {
        if (audioData == null || audioData.channels != 2) {
            throw new IllegalArgumentException("音频数据必须是双声道");
        }
        
        // 分离左右声道数据
        float[] leftChannel = extractChannel(audioData.data, audioData.channels, 0);
        float[] rightChannel = extractChannel(audioData.data, audioData.channels, 1);

        // 对左右声道分别进行下采样
        float[] downsampledLeft = downsample(leftChannel, audioData.sampleRate, targetRate);
        float[] downsampledRight = downsample(rightChannel, audioData.sampleRate, targetRate);

        // 分别计算左右声道的频谱图
        SpectrumAnalyzer spectrumAnalyzer = new SpectrumAnalyzer(targetRate, fftSize);
        double[][] leftSpectrogram = spectrumAnalyzer.computeSpectrogram(downsampledLeft, hopSize);
        double[][] rightSpectrogram = spectrumAnalyzer.computeSpectrogram(downsampledRight, hopSize);
        
        return new ChannelSpectrogram(leftSpectrogram, rightSpectrogram);
    }
    
    /**
     * 处理单声道音频数据并计算频谱图
     * 
     * @param audioData 单声道音频数据
     * @param targetRate 目标采样率
     * @param fftSize FFT窗口大小
     * @param hopSize Hop大小
     * @return 频谱图
     */
    public static double[][] processMonoChannel(AudioData audioData, int targetRate, int fftSize, int hopSize) {
        if (audioData == null || audioData.channels != 1) {
            throw new IllegalArgumentException("音频数据必须是单声道");
        }
        
        // 对音频数据进行下采样
        float[] downsampled = downsample(audioData.data, audioData.sampleRate, targetRate);
        
        // 计算频谱图
        SpectrumAnalyzer spectrumAnalyzer = new SpectrumAnalyzer(targetRate, fftSize);
        return spectrumAnalyzer.computeSpectrogram(downsampled, hopSize);
    }
    
    /**
     * 声道频谱图容器类
     */
    public static class ChannelSpectrogram {
        private final double[][] leftSpectrogram;
        private final double[][] rightSpectrogram;
        
        public ChannelSpectrogram(double[][] leftSpectrogram, double[][] rightSpectrogram) {
            this.leftSpectrogram = leftSpectrogram;
            this.rightSpectrogram = rightSpectrogram;
        }
        
        public double[][] getLeftSpectrogram() {
            return leftSpectrogram;
        }
        
        public double[][] getRightSpectrogram() {
            return rightSpectrogram;
        }
    }
}